/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO;

import DAO.exceptions.IllegalOrphanException;
import DAO.exceptions.NonexistentEntityException;
import DAO.exceptions.RollbackFailureException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import Entidad.Usuario;
import java.util.ArrayList;
import java.util.Collection;
import Entidad.Flujo;
import Entidad.Proyecto;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;

/**
 *
 * @author David
 */
public class ProyectoDAO implements Serializable, DAOinterface {

    public void create(Proyecto proyecto, EntityManager em) throws  Exception {
        if (proyecto.getUsuarioCollection() == null) {
            proyecto.setUsuarioCollection(new ArrayList<Usuario>());
        }
        if (proyecto.getFlujoCollection() == null) {
            proyecto.setFlujoCollection(new ArrayList<Flujo>());
        }
            Collection<Usuario> attachedUsuarioCollection = new ArrayList<Usuario>();
            for (Usuario usuarioCollectionUsuarioToAttach : proyecto.getUsuarioCollection()) {
                usuarioCollectionUsuarioToAttach = em.getReference(usuarioCollectionUsuarioToAttach.getClass(), usuarioCollectionUsuarioToAttach.getCorreo());
                attachedUsuarioCollection.add(usuarioCollectionUsuarioToAttach);
            }
            proyecto.setUsuarioCollection(attachedUsuarioCollection);
            Collection<Flujo> attachedFlujoCollection = new ArrayList<Flujo>();
            for (Flujo flujoCollectionFlujoToAttach : proyecto.getFlujoCollection()) {
                flujoCollectionFlujoToAttach = em.getReference(flujoCollectionFlujoToAttach.getClass(), flujoCollectionFlujoToAttach.getIdflujos());
                attachedFlujoCollection.add(flujoCollectionFlujoToAttach);
            }
            proyecto.setFlujoCollection(attachedFlujoCollection);
            em.persist(proyecto);
            for (Usuario usuarioCollectionUsuario : proyecto.getUsuarioCollection()) {
                Proyecto oldIdproyectoOfUsuarioCollectionUsuario = usuarioCollectionUsuario.getIdproyecto();
                usuarioCollectionUsuario.setIdproyecto(proyecto);
                usuarioCollectionUsuario = em.merge(usuarioCollectionUsuario);
                if (oldIdproyectoOfUsuarioCollectionUsuario != null) {
                    oldIdproyectoOfUsuarioCollectionUsuario.getUsuarioCollection().remove(usuarioCollectionUsuario);
                    oldIdproyectoOfUsuarioCollectionUsuario = em.merge(oldIdproyectoOfUsuarioCollectionUsuario);
                }
            }
            for (Flujo flujoCollectionFlujo : proyecto.getFlujoCollection()) {
                Proyecto oldIdproyectoOfFlujoCollectionFlujo = flujoCollectionFlujo.getIdproyecto();
                flujoCollectionFlujo.setIdproyecto(proyecto);
                flujoCollectionFlujo = em.merge(flujoCollectionFlujo);
                if (oldIdproyectoOfFlujoCollectionFlujo != null) {
                    oldIdproyectoOfFlujoCollectionFlujo.getFlujoCollection().remove(flujoCollectionFlujo);
                    oldIdproyectoOfFlujoCollectionFlujo = em.merge(oldIdproyectoOfFlujoCollectionFlujo);
                }
            }
    }

    public void edit(Proyecto proyecto, EntityManager em) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
        
        try {
            Proyecto persistentProyecto = em.find(Proyecto.class, proyecto.getIdproyecto());
            Collection<Usuario> usuarioCollectionOld = persistentProyecto.getUsuarioCollection();
            Collection<Usuario> usuarioCollectionNew = proyecto.getUsuarioCollection();
            Collection<Flujo> flujoCollectionOld = persistentProyecto.getFlujoCollection();
            Collection<Flujo> flujoCollectionNew = proyecto.getFlujoCollection();
            List<String> illegalOrphanMessages = null;
            for (Flujo flujoCollectionOldFlujo : flujoCollectionOld) {
                if (!flujoCollectionNew.contains(flujoCollectionOldFlujo)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Flujo " + flujoCollectionOldFlujo + " since its idproyecto field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Collection<Usuario> attachedUsuarioCollectionNew = new ArrayList<Usuario>();
            for (Usuario usuarioCollectionNewUsuarioToAttach : usuarioCollectionNew) {
                usuarioCollectionNewUsuarioToAttach = em.getReference(usuarioCollectionNewUsuarioToAttach.getClass(), usuarioCollectionNewUsuarioToAttach.getCorreo());
                attachedUsuarioCollectionNew.add(usuarioCollectionNewUsuarioToAttach);
            }
            usuarioCollectionNew = attachedUsuarioCollectionNew;
            proyecto.setUsuarioCollection(usuarioCollectionNew);
            Collection<Flujo> attachedFlujoCollectionNew = new ArrayList<Flujo>();
            for (Flujo flujoCollectionNewFlujoToAttach : flujoCollectionNew) {
                flujoCollectionNewFlujoToAttach = em.getReference(flujoCollectionNewFlujoToAttach.getClass(), flujoCollectionNewFlujoToAttach.getIdflujos());
                attachedFlujoCollectionNew.add(flujoCollectionNewFlujoToAttach);
            }
            flujoCollectionNew = attachedFlujoCollectionNew;
            proyecto.setFlujoCollection(flujoCollectionNew);
            proyecto = em.merge(proyecto);
            for (Usuario usuarioCollectionOldUsuario : usuarioCollectionOld) {
                if (!usuarioCollectionNew.contains(usuarioCollectionOldUsuario)) {
                    usuarioCollectionOldUsuario.setIdproyecto(null);
                    usuarioCollectionOldUsuario = em.merge(usuarioCollectionOldUsuario);
                }
            }
            for (Usuario usuarioCollectionNewUsuario : usuarioCollectionNew) {
                if (!usuarioCollectionOld.contains(usuarioCollectionNewUsuario)) {
                    Proyecto oldIdproyectoOfUsuarioCollectionNewUsuario = usuarioCollectionNewUsuario.getIdproyecto();
                    usuarioCollectionNewUsuario.setIdproyecto(proyecto);
                    usuarioCollectionNewUsuario = em.merge(usuarioCollectionNewUsuario);
                    if (oldIdproyectoOfUsuarioCollectionNewUsuario != null && !oldIdproyectoOfUsuarioCollectionNewUsuario.equals(proyecto)) {
                        oldIdproyectoOfUsuarioCollectionNewUsuario.getUsuarioCollection().remove(usuarioCollectionNewUsuario);
                        oldIdproyectoOfUsuarioCollectionNewUsuario = em.merge(oldIdproyectoOfUsuarioCollectionNewUsuario);
                    }
                }
            }
            for (Flujo flujoCollectionNewFlujo : flujoCollectionNew) {
                if (!flujoCollectionOld.contains(flujoCollectionNewFlujo)) {
                    Proyecto oldIdproyectoOfFlujoCollectionNewFlujo = flujoCollectionNewFlujo.getIdproyecto();
                    flujoCollectionNewFlujo.setIdproyecto(proyecto);
                    flujoCollectionNewFlujo = em.merge(flujoCollectionNewFlujo);
                    if (oldIdproyectoOfFlujoCollectionNewFlujo != null && !oldIdproyectoOfFlujoCollectionNewFlujo.equals(proyecto)) {
                        oldIdproyectoOfFlujoCollectionNewFlujo.getFlujoCollection().remove(flujoCollectionNewFlujo);
                        oldIdproyectoOfFlujoCollectionNewFlujo = em.merge(oldIdproyectoOfFlujoCollectionNewFlujo);
                    }
                }
            }
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = proyecto.getIdproyecto();
                if (findProyecto(id, em) == null) {
                    throw new NonexistentEntityException("The proyecto with id " + id + " no longer exists.");
                }
            }
            throw ex;
        }
    }

    public void destroy(Integer id, EntityManager em) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
            Proyecto proyecto;
            try {
                proyecto = em.getReference(Proyecto.class, id);
                proyecto.getIdproyecto();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The proyecto with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Collection<Flujo> flujoCollectionOrphanCheck = proyecto.getFlujoCollection();
            for (Flujo flujoCollectionOrphanCheckFlujo : flujoCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Proyecto (" + proyecto + ") cannot be destroyed since the Flujo " + flujoCollectionOrphanCheckFlujo + " in its flujoCollection field has a non-nullable idproyecto field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Collection<Usuario> usuarioCollection = proyecto.getUsuarioCollection();
            for (Usuario usuarioCollectionUsuario : usuarioCollection) {
                usuarioCollectionUsuario.setIdproyecto(null);
                usuarioCollectionUsuario = em.merge(usuarioCollectionUsuario);
            }
            em.remove(proyecto);
    }

    public List<Proyecto> findProyectoEntities(EntityManager em) {
        return findProyectoEntities(true, -1, -1, em);
    }

    public List<Proyecto> findProyectoEntities(int maxResults, int firstResult, EntityManager em) {
        return findProyectoEntities(false, maxResults, firstResult, em);
    }

    private List<Proyecto> findProyectoEntities(boolean all, int maxResults, int firstResult, EntityManager em) {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Proyecto.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
    }

    public Proyecto findProyecto(Integer id, EntityManager em) {
            return em.find(Proyecto.class, id);
    }

    public int getProyectoCount(EntityManager em) {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Proyecto> rt = cq.from(Proyecto.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
    }

    
}
